package sso.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 定义UserDetaisService接口的具体实现，在这个实现中定义用户登录逻辑
 */

@Service
public class UserDetailServiceImpl implements UserDetailsService {
    /**
     * @Autowired注解描述属性时的规则：
     * spring框架会依据@Autowired注解描述的属性类型，从spring容器查找对应的Bean,假如只找到一个则直接注入，假如找到多个
     * 还会对比属性名是否与容器中的Bean的名字是否相同，有则直接注入，没有则抛出异常。
     */
    @Autowired
    private BCryptPasswordEncoder passwordEncoder;

    /**
     * 当我们执行登录操作时，底层会通过过滤器等对象，调用这个方法
     * @param username 此参数为页面输出的用户名
     * @return 一般是从数据库基于用户名查询到的用户信息
     * @throws UsernameNotFoundException
     */

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //1.基于用户名从数据库查询用户信息
        //User user = userMapper.selectUserByUsername(username);
        if(!"xiongqiang".equals(username))throw new UsernameNotFoundException("用户不存在");
        //2.将用户信息封装到UserDetails对象中并返回
        //假设这个密码是从数据库中查询到的
        String encodedPwd = passwordEncoder.encode("123456");
        //假设这个权限信息是从数据库查询到的
        //假设分配权限的方式是角色，编写字符串时用的“ROLE_"做前缀，以下授予了搜索和新建的权限
        List<GrantedAuthority> grantedAuthorities =
                AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_admin,ROLE_normal,sys:res:retrieve,sys:res:create");

        //这个user是SpringSecurity提供的UserDetails接口的实现，用于封装用户信息
        User user = new User(username, encodedPwd,grantedAuthorities);
        return user;
    }
}
